/*
 * msgs.h
 *
 *  Created on: May 20, 2013
 *      Author: root
 */

#ifndef MSGS_H_
#define MSGS_H_

#define MSG_Q_LEN 10000

#include <pthread.h>
#include <semaphore.h>
#include "Lock.h"

struct MSG{
	long type;
	void *lParam;
	long value1;
	long value2;
	long value3;
};

class MSGQueue{
private:
	CLock 	_qLock;
	sem_t  	_qsem;
	MSG		msg[MSG_Q_LEN];
	long 	m_nStart;
	long	m_nEnd;
public:
	MSGQueue(){
		init();
	}

	virtual ~MSGQueue(){
		destroy();
	}

	int init(){
		m_nStart =0;
		m_nEnd =0;
		return sem_init(&_qsem,0,0);
	}

	void destroy(){
		sem_destroy(&_qsem);
	}

	int reset(){
		int retValue = 0;

		_qLock.Lock();
		m_nStart=m_nEnd=0;
		destroy();
		retValue = init();
		_qLock.Unlock();

		if(retValue != 0){
			printf("failed to init msg queue:%d\n",retValue);
		}

		return retValue;
	}

	void addMsg(long type){
		addMsg(type,NULL,0,0,0);
	}

	void addMsg(long type,void * lParam){
		addMsg(type,lParam,0,0,0);
	}

	void addMsg(long type,void * lParam,long value1){
		addMsg(type,lParam,value1,0,0);
	}

	void addMsg(long type,void * lParam,long value1,long value2){
		addMsg(type,lParam,value1,value2,0);
	}


	void addMsg(long type,void * lParam,long value1,long value2,long value3){
		//lock the queue;
		int nIndex;
		_qLock.Lock();
		nIndex = m_nEnd++;
		if(m_nEnd>=MSG_Q_LEN){
			m_nEnd = 0;
		}
		_qLock.Unlock();

		msg[nIndex].type = type;
		msg[nIndex].lParam = lParam;
		msg[nIndex].value1 = value1;
		msg[nIndex].value2 = value2;
		msg[nIndex].value3 = value3;

		sem_post(&_qsem);
	}

	/**
	 * NOTE:  wo don't LOCK because only the policy thread will call this method;
	 */
	MSG * getMsg(){
		sem_wait(&_qsem);
		MSG *pMsg = &msg[m_nStart];
		m_nStart++;

		if(m_nStart>=MSG_Q_LEN){
			m_nStart = 0;
		}
		return pMsg;
	}
};

#endif /* MSGS_H_ */
